/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package minesweeper.gameengine;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JFrame;
import minesweeper.components.Board;
import minesweeper.components.UI;
import minesweeper.gameaction.GameActionEvent;
import minesweeper.gameaction.GameActionListener;
import minesweeper.gameover.GameOverEvent;
import minesweeper.gameover.GameOverListener;
import minesweeper.util.Constants;

/**
 *
 * @author cj
 */
public class GameEngine extends JComponent implements ActionListener, GameActionListener, KeyListener{

    protected ArrayList<GameOverListener> gameOverListeners;

    protected Board theBoard;
    protected UI theUI;
    
    protected JFrame parentFrame;

    public GameEngine(JFrame parentFrame){
        initDisplay();
        initComponents();
        this.parentFrame = parentFrame;
    }

    private void initComponents(){
        this.gameOverListeners = new ArrayList<GameOverListener>();
        this.setLayout(new BorderLayout());
        
        this.theUI = new UI(Constants.GAME_NUM_COL, Constants.GAME_NUM_BOMBS);
        this.add(this.theUI, BorderLayout.NORTH);

        this.theBoard = new Board(Constants.GAME_NUM_COL, Constants.GAME_NUM_ROW,
                Constants.GAME_NUM_BOMBS);
        this.add(this.theBoard, BorderLayout.CENTER);
        
        this.theBoard.addGameActionListenerToAllSectors(this);
        this.theBoard.addGameOverListenersToEngine(this);
    }

    private void initDisplay(){
        this.setFocusable(true);
        this.addKeyListener(this);
        this.setVisible(true);
    }

    public void actionPerformed(ActionEvent e){
        repaint();
    }

    public void addGameOverListener(GameOverListener listener){
        this.gameOverListeners.add(listener);
    }

    private void notifyGameOverListeners(GameOverEvent e){
        for(int i = 0; i < this.gameOverListeners.size(); ++i){
            this.gameOverListeners.get(i).gameOverTriggered(e);
        }
    }

    private void runGameOver(GameActionEvent e){
        this.theUI.stopGame();
        this.notifyGameOverListeners(new GameOverEvent(e.getOrginSector(), e.getTimeStamp()));
    }

    public void gameActionPerformed(GameActionEvent e){

        if(!this.theUI.isGameStarted() && !this.theUI.hasGameRun()){
            this.theUI.setStartTime(e.getTimeStamp());
            this.theUI.startGame();
        }

        switch(e.getActionType()){
            case SAFE_SECTOR_SELECTED:
                //Safe Sector Selected: Increment Score
                System.out.println("Incrementing Score.");
                this.theUI.setCurrentScore(this.theUI.getCurrentScore() + 10);
                break;
            case BOMB_SECTOR_SELECTED:
                //End game
                System.out.println("Current Game Over.");
                this.runGameOver(e);
                break;
            case FLAGGED_SECTOR:
                //Sector Flagged
                System.out.println("Flagged One Sector.");
                this.theUI.setNumFlaggedLeft(this.theUI.getNumFlaggedLeft() - 1);
                break;
            case UNFLAGGED_SECTOR:
                //Sector Unflagged
                System.out.println("UnFlagged One Sector.");
                this.theUI.setNumFlaggedLeft(this.theUI.getNumFlaggedLeft() + 1);
                break;
        }
    }
    
    private void resetGame(){
        System.out.println("Resetting Game.");
        this.removeAll();
        initComponents();
        
        //Need repack to redisplay after clearing the container
        this.parentFrame.pack();
    }
    
    public void keyPressed(KeyEvent e){
        System.out.println("Key Pressed.");
        if(this.theUI.hasGameRun() && !this.theUI.isGameStarted()){
            //Game over state, look for reset key
            System.out.println("Key Input in Game Over State.");
            if(e.getKeyCode() == KeyEvent.VK_SPACE){
                resetGame();
            }
        }
    }
    
    public void keyTyped(KeyEvent e){
    }
    
    
    public void keyReleased(KeyEvent e){
    }

}
